﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Proxificator;
using System.Threading;
using Microsoft.Win32;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;

namespace TesClient
{
    public sealed partial class Form1 : Form
    {   
        private List<Proxificator.Proxy> kumProxy = new List<Proxificator.Proxy>();
        private SortedSet<string> countryList = new SortedSet<string>();
        private bool stopTimer = false;
        private DateTime dt = new DateTime();
        TimeSpan timeSpan = new TimeSpan();

        private List<ListBox> listBoxProxy = new List<ListBox>();

        public Form1()
        {
            InitializeComponent();

            dt = DateTime.Now;
            comboThread.SelectedIndex = 10;
            comboTimeOut.SelectedIndex = 14;
            comboInterval.SelectedIndex = 0;
            radioAsc.Checked = true;
            sourceJudge.SelectedIndex = 0;

            listBoxProxy.Add(listBoxElite);
            listBoxProxy.Add(listBoxAnonymous);
            listBoxProxy.Add(listBoxTransparent);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            button4.Enabled = false;
            button5.Enabled = false;
            stopTimer = false;
            List<Proxificator.Proxy> kumProxy = new List<Proxificator.Proxy>();
            StringBuilder sb = new StringBuilder();
            bool belumrampung = true;

            Thread t = new Thread(() =>
            {
                kumProxy = Proxificator.Proxificator.extractProxy(source.Text);
                using (StringReader sr = new StringReader(textBox3.Text))
                {
                    string s;
                    while (!(String.IsNullOrEmpty(s = sr.ReadLine())))
                    {
                        kumProxy.Add(new Proxificator.Proxy(s, 0, "Unknown"));
                    }
                }
                Proxificator.Proxificator.removeDuplicate(ref kumProxy);
                foreach (Proxificator.Proxy pr in kumProxy)
                {
                    sb.Append(pr.vIpPort).AppendLine();
                }
                belumrampung = false;
            });
            t.IsBackground = true;
            t.Start();

            while (belumrampung)
            {
                Application.DoEvents();
            }

            textBox3.Text = sb.ToString();
            sb = null;
            kumProxy = null;

            if (comboInterval.Text != "Disabled")
            {
                timer2.Interval = (Convert.ToInt32(comboInterval.Text) * 1000);
                timer2.Start();
            }
            else
            {
                button4.Enabled = true;
                button5.Enabled = true;
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (button5.Text == "JUDGE")
            {
                kumProxy = new List<Proxificator.Proxy>();
                using (StringReader sr = new StringReader(textBox3.Text))
                {
                    string s;
                    while (!(String.IsNullOrEmpty(s = sr.ReadLine())))
                    {
                        kumProxy.Add(new Proxificator.Proxy(s, 0, "Unknown"));
                    }
                }
                Proxificator.Proxificator.removeDuplicate(ref kumProxy);
                StringBuilder sb = new StringBuilder();
                foreach (Proxificator.Proxy pr in kumProxy)
                {
                    sb.Append(pr.vIpPort).AppendLine();
                }
                textBox3.Text = sb.ToString();

                button5.Text = "STOP";
                //button5.Enabled = false;
                button4.Enabled = false;
                setProxy.Enabled = false;
                groupBoxProxyResult.Enabled = false;
                countryCombo.Items.Clear();
                countryList.Clear();
                progressBar1.Maximum = kumProxy.Count;
                progressBar1.Value = 0;

                Proxificator.Proxificator.vTimeOut = Convert.ToInt32(comboTimeOut.Text);
                Proxificator.Proxificator.vMaxThread = Convert.ToInt32(comboThread.Text);
                Proxificator.Proxificator.vSourceJudge = sourceJudge.Text;

                Thread t = new Thread(() => Proxificator.Proxificator.Judge(ref kumProxy));
                t.IsBackground = true;
                t.Start();
                //ThreadPool.QueueUserWorkItem(param => Proxificator.Proxificator.Judge(ref kumProxy));
                dt = DateTime.MinValue;
                ThreadPool.QueueUserWorkItem(param => { t.Join(); dt = DateTime.Now; });
                timer1.Start();
            }
            else
            {
                button5.Enabled = false;
                Thread t = new Thread(() => Proxificator.Proxificator.stopJudge());
                t.IsBackground = true;
                t.Start();
            }
        }

        private void updateStats()
        {
            countElite.Text = Proxificator.Proxificator.elite.ToString();
            countAnonymous.Text = Proxificator.Proxificator.anonymous.ToString();
            countTransparent.Text = Proxificator.Proxificator.transparent.ToString();
            countBadProxy.Text = Proxificator.Proxificator.badProxy.ToString();
            countBadData.Text = Proxificator.Proxificator.badData.ToString();
        }

        private void updateTabProxy()
        {
            List<Proxy> ls = new List<Proxy>();
            int indeks = tabControlProxyResult.SelectedIndex;

            if (String.IsNullOrEmpty(countryCombo.Text))
            {
                foreach (Proxificator.Proxy pr in kumProxy)
                {
                    if (pr.vStatus == indeks + 1)
                        ls.Add(pr);
                }
            }
            else
            {
                foreach (Proxificator.Proxy pr in kumProxy)
                {
                    if (pr.vCountry == countryCombo.Text)
                    {
                        if (pr.vStatus == indeks + 1)
                            ls.Add(pr);
                    }
                }
            }

            if (radioAsc.Checked)
            {
                ls.Sort(ProxyComparerSpeed.Ascending);
            }
            else
            {
                ls.Sort(ProxyComparerSpeed.Descending);
            }

            if (listBoxProxy.Count > 0)
            {
                listBoxProxy[indeks].DataSource = ls;
            }
            
            ls = null;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (Proxificator.Proxificator.threadAlive == 0 && dt != DateTime.MinValue)
            {
                timer1.Enabled = false;
                timer1.Stop();
                Proxificator.Proxificator.waitAllThreadTerminated();

                foreach (Proxificator.Proxy pr in kumProxy)
                {
                    if (pr.vCountry != "Unknown" && pr.vStatus > 0)
                        countryList.Add(pr.vCountry);
                }
                foreach (string st in countryList)
                {
                    countryCombo.Items.Add(st);
                }
                countryList.Clear();
                proxyChecked.Text = Convert.ToString(Proxificator.Proxificator.proxyChecked);
                threadAlive.Text = Convert.ToString(Proxificator.Proxificator.threadAlive);
                progressBar1.Value = Proxificator.Proxificator.totalProxy;
                updateStats();
                updateTabProxy();

                button5.Text = "JUDGE";
                button5.Enabled = true;
                button4.Enabled = true;
                setProxy.Enabled = true;
                groupBoxProxyResult.Enabled = true;
                /*foreach (Proxificator.Proxy pr in kumProxy)
                {
                    if (pr.vStatus != 0)
                    {
                        System.IO.File.AppendAllText(@"D:\PBK\WriteText.txt", pr.vIpPort + " " + pr.vCountry + " " + pr.vStatus + " " + pr.vSpeed + "\n");
                    }
                }*/
                timeSpan = DateTime.Now - dt;
                MessageBox.Show(Convert.ToString(timeSpan.Hours) + " hours " + Convert.ToString(timeSpan.Minutes) + " minutes " + Convert.ToString(timeSpan.Seconds) + " seconds " + "\n");
                                //+ Convert.ToString(timesw123));
            }
            else
            {
                if (Proxificator.Proxificator.proxyChecked < kumProxy.Count)
                {
                    proxyChecked.Text = Convert.ToString(Proxificator.Proxificator.proxyChecked);
                    progressBar1.Value = Proxificator.Proxificator.proxyChecked;
                }
                updateStats();
                threadAlive.Text = Convert.ToString(Proxificator.Proxificator.threadAlive);
            }
        }

        private void setGlobalProxy()
        {
            Proxy pr = listBoxProxy[tabControlProxyResult.SelectedIndex].SelectedItem as Proxy;
            bool success = false;
            try
            {
                success = Proxificator.Proxificator.setProxy(pr);
            }
            catch (Exception ex)
            {
                MessageBox.Show("ERROR!!!\n" + ex.Message);
            }

            if (success)
            {
                MessageBox.Show("The selected proxy (" + pr.vIpPort +") has been successfully set.");
            }
        }

        private void setProxy_Click(object sender, EventArgs e)
        {
            setGlobalProxy();
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            List<Proxificator.Proxy> kumProxy = new List<Proxificator.Proxy>();
            kumProxy = Proxificator.Proxificator.extractProxy(source.Text);
            StringBuilder sb = new StringBuilder();
            foreach (Proxificator.Proxy pr in kumProxy)
            {
                sb.Append(pr.vIpPort).AppendLine();
            }
            textBox3.AppendText(sb.ToString());
            kumProxy = null;
            sb = null;
            if (stopTimer)
            {
                kumProxy = new List<Proxificator.Proxy>();
                using (StringReader sr = new StringReader(textBox3.Text))
                {
                    string s;
                    while (!(String.IsNullOrEmpty(s = sr.ReadLine())))
                    {
                        kumProxy.Add(new Proxificator.Proxy(s, 0, "Unknown"));
                    }
                }
                Proxificator.Proxificator.removeDuplicate(ref kumProxy);
                sb = new StringBuilder();
                foreach (Proxificator.Proxy pr in kumProxy)
                {
                    sb.Append(pr.vIpPort).AppendLine();
                }
                textBox3.Text = sb.ToString();
                button4.Enabled = true;
                button5.Enabled = true;
                timer2.Stop();
            }
        }

        private void stop_Click(object sender, EventArgs e)
        {
            stopTimer = true;
        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
            count.Text = textBox3.Lines.Length.ToString();
        }

        private void loadProxyListFromFilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stream myStream = null;
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 0;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if ((myStream = openFileDialog1.OpenFile()) != null)
                    {
                        using (myStream)
                        {
                            using (StreamReader sr = new StreamReader(myStream))
                            {
                                textBox3.AppendText(sr.ReadToEnd());
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void getProxyInfo()
        {
            Proxy pr = listBoxProxy[tabControlProxyResult.SelectedIndex].SelectedItem as Proxy;
            infoCountry.Text = pr.vCountry;
            infoIpPort.Text = pr.vIpPort;
            infoSpeed.Text = pr.vSpeed.ToString();
            infoStatus.Text = pr.vStatus.ToString();
        }

        private void listBoxElite_SelectedIndexChanged(object sender, EventArgs e)
        {
            getProxyInfo();
        }

        private void listBoxAnonymous_SelectedIndexChanged(object sender, EventArgs e)
        {
            getProxyInfo();
        }

        private void listBoxTransparent_SelectedIndexChanged(object sender, EventArgs e)
        {
            getProxyInfo();
        }

        private void tabControlProxyResult_SelectedIndexChanged(object sender, EventArgs e)
        {
            updateTabProxy();
        }

        private void radioAsc_CheckedChanged(object sender, EventArgs e)
        {
            updateTabProxy();
        }

        private void countryCombo_TextChanged(object sender, EventArgs e)
        {
            updateTabProxy();
        }

        private void eliteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<Proxificator.Proxy> kumProxy = new List<Proxificator.Proxy>();
            StringBuilder sb = new StringBuilder();

            using (StringReader sr = new StringReader(textBox3.Text))
            {
                string s;
                while (!(String.IsNullOrEmpty(s = sr.ReadLine())))
                {
                    kumProxy.Add(new Proxificator.Proxy(s, 0, "Unknown"));
                }
            }
            Proxificator.Proxificator.removeDuplicate(ref kumProxy);
            foreach (Proxificator.Proxy pr in kumProxy)
            {
                sb.Append(pr.vIpPort).AppendLine();
            }
            textBox3.Text = sb.ToString();

            sb = null;
            kumProxy = null;
        }

        private void saveProxyList(object sender)
        {
            Stream myStream;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();

            saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 2;
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = saveFileDialog1.OpenFile()) != null)
                {
                    using (StreamWriter sw = new StreamWriter(myStream))
                    {
                        int indeks = Convert.ToInt32(((ToolStripMenuItem)sender).Tag);
                        foreach (object o in listBoxProxy[indeks].Items)
                        {
                            sw.WriteLine(o.ToString());
                        }
                    }
                    myStream.Close();
                }
            }
            MessageBox.Show("Proxy List saved successfully.");
        }

        private void eliteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            saveProxyList(sender);
        }

        private void anonymousToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            saveProxyList(sender);
        }

        private void transparentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveProxyList(sender);
        }

        private void aLLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Stream myStream;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();

            saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 2;
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if ((myStream = saveFileDialog1.OpenFile()) != null)
                {
                    using (StreamWriter sw = new StreamWriter(myStream))
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            foreach (object o in listBoxProxy[i].Items)
                            {
                                sw.WriteLine(o.ToString());
                            }
                        }
                    }
                    myStream.Close();
                }
            }
            MessageBox.Show("Proxy List saved successfully.");
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            using (FormAbout about = new FormAbout())
            {
                about.ShowDialog();
            }
        }
    }

    public sealed class ProxyComparerSpeed : IComparer<Proxy>
    {
        public static IComparer<Proxy> Ascending = getInstance(1);
        public static IComparer<Proxy> Descending = getInstance(2);
        private int mode;

        private static IComparer<Proxy> getInstance(int mode)
        {
            if (mode == 1)
            {
                if (Ascending == null)
                {
                    return new ProxyComparerSpeed(mode);
                }
                else
                {
                    return Ascending;
                }
            }
            else
            {
                if (Descending == null)
                {
                    return new ProxyComparerSpeed(mode);
                }
                else
                {
                    return Descending;
                }
            }
        }

        private ProxyComparerSpeed()
        {

        }
        private ProxyComparerSpeed(int mode)
        {
            this.mode = mode;
        }

        public int Compare(Proxy pr1, Proxy pr2)
        {
            if (mode == 1)
            {
                return Comparer.Default.Compare(pr1.vSpeed, pr2.vSpeed);
            }
            else
            {
                return Comparer.Default.Compare(pr2.vSpeed, pr1.vSpeed);
            }
        }
    }

}
